package net.alche.al.util.far.pojo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.alche.al.util.Far;
@SuppressWarnings("all") 
public class VueProxy<T> {
    VueDom dom;
    String domAttr;
    VueProxy fromPr;
    String fromCol;
    static int idCount = 1;
    int sameCount = 0;
    public T v;
    public T oldV;
    public boolean hasChange = false;
    private Map<Integer, VueFunction> watchMap;
    //    private Map<String, VueDom> domMap;
//    public Map<String, String> colMap;
    List<VueProxyLiker> likerList;
    List<VueLamadaDo> lamadaList;

    class VueProxyLiker {
        VueProxy toProxy;
        //        VueDom dom;
        String attrName; // text src ...
        String col; // v.col
    }

    public VueProxy(VueDom dom, String attr) {
        this.dom = dom;
        this.domAttr = attr;
    }

    public VueProxy() {

    }

    public void gv(Object v) {
        this.v = (T) v;
        this.render();
    }

    public void gv(String col, Object v) {
        Far.java.setAttr(this.v, col, v);
        this.render(true);
    }

    List<VueProxyLiker> getLikerList() {
        if (this.likerList == null) {
            likerList = new ArrayList<>();
        }
        return this.likerList;
    }

    public VueProxy(Object obj) {
        if (obj != null) {
            v = (T) obj;
        }
    }

    public void linkDom(String attrName, VueDom dom) {
        this.linkDom(attrName, dom, null);
    }

    public void linkDom(String attrName, VueDom dom, String col) {
        VueProxyLiker liker = new VueProxyLiker();
        VueProxy domPr = new VueProxy(dom, attrName);

        liker.toProxy = domPr;
        liker.attrName = attrName;
        liker.col = col;
        getLikerList().add(liker);
        if ("v-model".equals(attrName)) {
            domPr.fromPr = this;
            domPr.fromCol = col;
        }
        if (col == null) {
            domPr.v = this.v;
        } else {
            Object objVal = Far.java.getAttr(v, col);
            domPr.v = objVal;
        }
        if (dom != null) {
            dom.putProp(attrName, domPr);
        }
    }

//    public void render(String col) {
//        this.render(col);
//    }

//    public void render(String col) {
//        render(col);
//    }

    // , boolean ignWatch, VueProxy ignorTo
    public void renderVmodel() {
        if (this.fromPr != null) {
            if (this.fromCol != null && this.fromPr.v != null) {
                Far.java.setAttr(this.fromPr.v, this.fromCol, this.v);
                this.fromPr.render(this.fromCol);
            } else {
                this.fromPr.v = this.v;
                this.fromPr.render();
            }
        }
    }

    public void r() {
        render();
    }

    public void render(String col) {
        if (this.likerList != null) {
            for (VueProxyLiker liker : this.likerList) {
                if (liker.col != null && liker.col.equals(col)) {// && (ignorTo == null || !liker.toProxy.equals(ignorTo))) {
                    Object objVal = Far.java.getAttr(v, liker.col);
                    if (liker.toProxy != null) {
                        liker.toProxy.v = objVal;
                        liker.toProxy.render();
                    }

                }
            }
        }
        this.refreshLamada();
    }

    public void renderOnce() {
        render(true);
    }

    public void render() {
        render(false);
    }

    public void render(boolean once) {
//        Far.log("once",once);
        if (!once && (v == null && oldV == null || v != null && oldV != null && v.equals(oldV))) {
            return;
        }
        oldV = v;
        if (dom != null) {
            dom.render(domAttr, v, this);
        }
        if (likerList != null) {
            for (VueProxyLiker liker : this.likerList) {
                if (liker.toProxy != null) {
                    if (liker.col != null) {
                        liker.toProxy.v = Far.java.getAttr(this.v, liker.col);
                    } else {
                        liker.toProxy.v = this.v;
                    }
                    liker.toProxy.render(once);
                }
            }
        }
        if (this.watchMap != null) {
            for (VueFunction fun : this.watchMap.values()) {
                fun.callVals(this.v, this.oldV);
            }
        }
        this.refreshLamada();
    }

    void refreshLamada() {
        if (lamadaList == null) return;
        for (VueLamadaDo lam : lamadaList) {
            lam.render();
        }
    }

    public void linkLamada(VueLamadaDo lamada) {
        if (lamadaList == null) lamadaList = new ArrayList<>();
        lamadaList.add(lamada);
    }

    public void putWatch(VueFunction fun) {
        if (this.watchMap == null) {
            this.watchMap = new HashMap<>();
        }
        fun.uniId = idCount++;
        this.watchMap.put(fun.uniId, fun);
    }

    public VueProxy prox(String val) {
        VueProxy pr = new VueProxy();
        pr.fromPr = this;
        pr.fromCol = val;
        if (this.v != null) {
            if (val != null) {
                Object attr = Far.java.getAttr(this.v, val);
                if (attr != null) {
                    pr.v = attr;
                }
            } else {
                pr.v = this.v;
            }
        }
        VueProxyLiker liker = new VueProxyLiker();
        liker.toProxy = pr;
        liker.col = val;
        getLikerList().add(liker);
        return pr;
    }
}
